//package com.yifushidai.config;
//
//import com.yifushidai.entity.*;
//import com.yifushidai.mapper.BandLockEntityMapper;
//import com.yifushidai.mapper.IdcardEntityMapper;
//import com.yifushidai.mapper.OpenRecordEntityMapper;
//import com.yifushidai.mapper.OptDeviceLogMapper;
//import com.yifushidai.utils.*;
//import org.apache.commons.lang.StringUtils;
//import org.apache.mina.core.buffer.IoBuffer;
//import org.apache.mina.core.service.IoHandler;
//import org.apache.mina.core.session.IdleStatus;
//import org.apache.mina.core.session.IoSession;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//
//import java.io.*;
//import java.text.ParseException;
//import java.util.Date;
//import java.util.LinkedHashMap;
//import java.util.List;
//import java.util.Map;
//import java.util.concurrent.ConcurrentHashMap;
//
//public class ApartmentIoHandler implements IoHandler {
//
//    private Logger logger = LoggerFactory.getLogger(ApartmentIoHandler.class);
//    public static ConcurrentHashMap<String, IoSession> sessionsConcurrentHashMap = new ConcurrentHashMap<String, IoSession>();//线程安全  服务端推送至硬件端用
//
//    @Autowired
//    private IdcardEntityMapper idcardEntityMapper;
//    @Autowired
//    private BandLockEntityMapper lockMapper;
//    @Autowired
//    private OpenRecordEntityMapper openRecordMapper;
//    @Autowired
//    private OptDeviceLogMapper optDeviceLogMapper;
//
//    @Override
//    public void sessionCreated(IoSession ioSession) throws Exception {
//        String remoteAddressAndSocket = ioSession.getRemoteAddress().toString();//192.168.1.3:55813
//        ioSession.setAttribute("remoteAddressAndSocket", remoteAddressAndSocket);
//        // 此处不应该：设置IoSession闲置时间，参数单位是秒
//        // ioSession.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
//    }
//
//    @Override
//    public void sessionOpened(IoSession ioSession) throws Exception {
//    }
//
//    @Override
//    public void sessionIdle(IoSession ioSession, IdleStatus idleStatus) {
//        String uniqueMac = (String) ioSession.getAttribute("UniqueMac");
//        String powerMac = (String) ioSession.getAttribute("PowerMac");
//        String remoteAddressAndSocket = (String) ioSession.getAttribute("remoteAddressAndSocket");
//        logger.error("xxx {}：{}({}_{})", idleStatus, remoteAddressAndSocket, uniqueMac, powerMac);
//        if (idleStatus == IdleStatus.BOTH_IDLE) {
//            ioSession.closeNow();//重连
//        }
//    }
//
//    @Override
//    public void exceptionCaught(IoSession ioSession, Throwable throwable) {
//        String uniqueMac = (String) ioSession.getAttribute("UniqueMac");
//        String powerMac = (String) ioSession.getAttribute("PowerMac");
//        String remoteAddressAndSocket = (String) ioSession.getAttribute("remoteAddressAndSocket");
//        logger.error("xxx exceptionCaught：{}({}_{})\n{}\n{}", remoteAddressAndSocket, uniqueMac, powerMac, throwable.getMessage(), throwable);
//        ioSession.closeNow();//重连
//    }
//
//    @Override
//    public void sessionClosed(IoSession ioSession) throws ParseException {
//        String uniqueMac = (String) ioSession.getAttribute("UniqueMac");
//        String powerMac = (String) ioSession.getAttribute("PowerMac");
//        String remoteAddressAndSocket = (String) ioSession.getAttribute("remoteAddressAndSocket");
//        boolean uniqueFlag = StringUtils.isNotBlank(uniqueMac) && uniqueMac.matches("^\\w{24}$");
//        boolean powerFlag = StringUtils.isNotBlank(powerMac) && powerMac.matches("^\\w{24}$");
//        logger.error("xxx sessionClosed：{}({}_{})", remoteAddressAndSocket, uniqueMac, powerMac);
//        if (uniqueFlag) {
//            BandLockEntity bl = lockMapper.queryDelFlagByMac(uniqueMac);
//            if (!powerFlag) {//uniqueMac通道
////                sessionsConcurrentHashMap.remove(uniqueMac);//IoSession关闭前处理：map移除当前ioSession，更新离线状态，释放连接
//                bl.setLs(CustomPackUtils.OFF_LINE);
//                optDeviceLogMapper.insertSelective(new OptDeviceLog(remoteAddressAndSocket, uniqueMac, null, bl.getAddr() + bl.getAlias(), "联网设备掉线", new Date(new Date().getTime() - 20000)));//操作日志
//            } else {//powerMac通道
//                //通道一心跳(离线) >>> 通道二重连(在线，map更新) >>> 通道一闲置(离线，map移除) >>> 通道二心跳(在线，map移除，无法推送)
////                sessionsConcurrentHashMap.remove(powerMac);//IoSession关闭前处理：map移除当前ioSession，更新离线状态，释放连接
//                bl.setPowerStatus(CustomPackUtils.OFF_LINE);
//
//                optDeviceLogMapper.insertSelective(new OptDeviceLog(remoteAddressAndSocket, uniqueMac, powerMac, bl.getAddr() + bl.getAlias(), "控电设备掉线", new Date(new Date().getTime() - 20000)));//操作日志
//            }
//            lockMapper.updateByPrimaryKeySelective(bl);
//        }
//    }
//
//    /**
//     * 接收与发送16进制数据包：
//     * 1、不设置过滤器编码
//     * 2、获取：messageReceived中
//     * 3、写入
//     */
//    @Override
//    public void messageReceived(IoSession ioSession, Object o) throws Exception {
//        String uniqueMac = (String) ioSession.getAttribute("UniqueMac");
//        String powerMac = (String) ioSession.getAttribute("PowerMac");
//        String remoteAddressAndSocket = (String) ioSession.getAttribute("remoteAddressAndSocket");
//        IoBuffer ioBuffer = (IoBuffer) o;
//        String message = ioBuffer.getHexDump().replaceAll("\\s*", "");
//        logger.warn("<<< 硬件端：{}({}_{}) 参数：{}", remoteAddressAndSocket, uniqueMac, powerMac, message);
//
//        //消息头解析
//        if (!message.startsWith(CustomPackUtils.HEAD_HEX)) return;
//        byte[] mainPackage = HexUtils.hexStringToBytes(message);
//        if (mainPackage == null) return;
//        byte[] payloadBytes = CustomPackUtils.unpack(mainPackage);
//        if (payloadBytes == null) return;
//        byte sourceByte = mainPackage[CustomPackUtils.HEAD_OFFSET + CustomPackUtils.LEN_OFFSET];
//        byte destByte = mainPackage[CustomPackUtils.HEAD_OFFSET + CustomPackUtils.LEN_OFFSET + CustomPackUtils.SOURCE_OFFSET];
//        if (destByte != CustomPackUtils.SERVER_DEVICE_ID) return;
//        byte msgByte = mainPackage[CustomPackUtils.HEAD_OFFSET + CustomPackUtils.LEN_OFFSET + CustomPackUtils.SOURCE_OFFSET + CustomPackUtils.DEST_OFFSET];
//
//
//        //消息ID：接收端根据这个编号来确定有效载荷里的消息类容（消息类型）
//        ResultLock resultLock;
//        switch (msgByte) {
//            case CustomPackUtils.MAC_INIT_MSG_ID://设备初始化：设备与云端服务器首次建立连接或断线重连，传送设备mac
//                uniqueMac = HexUtils.bytesToHexString(payloadBytes);
//                BandLockEntity bandlock = lockMapper.queryByMac(uniqueMac);
//                if (bandlock == null) {// 数据库mac未绑定
//                    bandlock = new BandLockEntity();
//                    bandlock.setMobile("17711351006");
//                    bandlock.setMac(uniqueMac);
//                    bandlock.setLs(CustomPackUtils.ON_LINE);
//                    bandlock.setUniqueType(HexUtils.bytesToHexString(new byte[]{sourceByte}));
//                    bandlock.setBluetooth("test");
//                    bandlock.setAlias("公寓测试");
//                    bandlock.setAddr("易福时代");
//                    lockMapper.insertSelective(bandlock);
//                } else {
//                    bandlock.setLs(CustomPackUtils.ON_LINE);
//                    lockMapper.updateLsByMac(bandlock);
//                }
//                ioSession.setAttribute("UniqueMac", uniqueMac);// 添加mac 到当前ioSession，心跳维持
//                sessionsConcurrentHashMap.put(uniqueMac, ioSession);// 添加当前ioSession 到静态集合 服务端推送至硬件端用
//
//                optDeviceLogMapper.insertSelective(new OptDeviceLog(remoteAddressAndSocket, uniqueMac, null, bandlock.getAddr() + bandlock.getAlias(), "联网设备重连"));//操作日志
//                break;
//
//            case CustomPackUtils.DEVICE_RESPONSE_MSG_ID://硬件端应答
//                if (StringUtils.isBlank(uniqueMac) || !uniqueMac.matches("^\\w{24}$")) {//从ioSession中取mac，为空则重连
//                    ioSession.closeNow();//重连
//                    return;
//                }
//                bandlock = lockMapper.queryByMac(uniqueMac);
//                if (bandlock == null || bandlock.getLs() == 0) {
//                    return;//重试
//                }
//                String res = HexUtils.bytesToHexString(payloadBytes);
//                resultLock = ApartmentMinaPushUtils.lockMap.get(uniqueMac);
//                if (resultLock != null) {
//                    synchronized (resultLock) {
//                        resultLock.notify();
//                        resultLock.setMessage(res);//结果值
//                    }
//                }
//
//                optDeviceLogMapper.insertSelective(new OptDeviceLog(remoteAddressAndSocket, uniqueMac, powerMac, bandlock.getAddr() + bandlock.getAlias(), "设备应答" + res));//操作日志
//                break;
//
//            case CustomPackUtils.IDCARD_UNPACK_MSG_ID://录入身份证信息：身份证读卡器与云端服务器数据交互，有效载荷含2个子包：身份证信息包（前1289字节）、身份证UID包（后19字节）
//                if (StringUtils.isBlank(uniqueMac) || !uniqueMac.matches("^\\w{24}$")) {//从ioSession中取mac，为空则重连
//                    ioSession.closeNow();//重连
//                    return;
//                }
//                bandlock = lockMapper.queryByMac(uniqueMac);
//                if (bandlock == null || bandlock.getLs() == 0) {
//                    return;//重试
//                }
//                IdcardEntity idcardEntity = QianjingPackUtils.unpack(payloadBytes);
//                if (idcardEntity == null) return;
//                IdcardEntity dbIdcardEntity = idcardEntityMapper.selectByUid(idcardEntity.getUid());
//                if (dbIdcardEntity == null) {
//                    idcardEntityMapper.insertSelective(idcardEntity);
//                } else {
//                    idcardEntity.setId(dbIdcardEntity.getId());
//                    idcardEntity.setUpdateTime(new Date());
//                    idcardEntityMapper.updateByPrimaryKeySelective(idcardEntity);
//                }
//                resultLock = ApartmentMinaPushUtils.lockMap.get(uniqueMac);
//                if (resultLock != null) {
//                    synchronized (resultLock) {
//                        resultLock.notify();
//                        resultLock.setMessage(idcardEntity);//结果值
//                    }
//                }
//
//                optDeviceLogMapper.insertSelective(new OptDeviceLog(remoteAddressAndSocket, uniqueMac, null, bandlock.getAddr() + bandlock.getAlias(), "身份证解析成功"));//操作日志
//                break;
//
//            case CustomPackUtils.LOCK_POWER_MSG_ID://联网盒向服务器发送锁电量
//                if (StringUtils.isBlank(uniqueMac) || !uniqueMac.matches("^\\w{24}$")) {//从ioSession中取mac，为空则重连
//                    ioSession.closeNow();//重连
//                    return;
//                }
//                bandlock = lockMapper.queryByMac(uniqueMac);
//                if (bandlock == null || bandlock.getLs() == 0) {
//                    return;//重试
//                }
//                String lockPowerResult = HexUtils.bytesToHexString(payloadBytes);
//                if (CustomPackUtils.LOCK_POWER_NORMAL_HEX_CMD.equals(lockPowerResult)) {
//                    bandlock.setLes(CustomPackUtils.ON_LINE);
//                    lockMapper.updateByPrimaryKeySelective(bandlock);
//
//                    optDeviceLogMapper.insertSelective(new OptDeviceLog(remoteAddressAndSocket, uniqueMac, null, bandlock.getAddr() + bandlock.getAlias(), "门锁设备电量正常"));//操作日志
//                } else if (CustomPackUtils.LOCK_POWER_LOWER_HEX_CMD.equals(lockPowerResult)) {
//                    bandlock.setLes(CustomPackUtils.OFF_LINE);
//                    lockMapper.updateByPrimaryKeySelective(bandlock);
//                    //推送。。。。。
//                    JPushUtils.apartmentPush(bandlock.getMobile(), "尊敬的房东您好，" + bandlock.getAlias() + "号房间门锁设备电量低，请及时更换电池", "电量提醒");
//
//                    optDeviceLogMapper.insertSelective(new OptDeviceLog(remoteAddressAndSocket, uniqueMac, null, bandlock.getAddr() + bandlock.getAlias(), "门锁设备电量低"));//操作日志
//                } else {
//                    return;//重试
//                }
//                break;
//
//            case CustomPackUtils.LOCK_OPEN_MSG_ID://联网盒向服务器发送开门结果
//                if (StringUtils.isBlank(uniqueMac) || !uniqueMac.matches("^\\w{24}$")) {//从ioSession中取mac，为空则重连
//                    ioSession.closeNow();//重连
//                    return;
//                }
//                bandlock = lockMapper.queryByMac(uniqueMac);
//                if (bandlock == null || bandlock.getLs() == 0) {
//                    return;//重试
//                }
//                String lockOpenResult = HexUtils.bytesToHexString(payloadBytes);
//                //插入开门记录
//                int result;
//                if (CustomPackUtils.LOCK_OPEN_FAIL_HEX_CMD.equals(lockOpenResult)) {
//                    result = 1;
//                    optDeviceLogMapper.insertSelective(new OptDeviceLog(remoteAddressAndSocket, uniqueMac, null, bandlock.getAddr() + bandlock.getAlias(), lockOpenResult + " 开门失败"));//操作日志
//                } else if (lockOpenResult.matches("^D\\w$")) {
//                    result = 0;
//                    optDeviceLogMapper.insertSelective(new OptDeviceLog(remoteAddressAndSocket, uniqueMac, null, bandlock.getAddr() + bandlock.getAlias(), lockOpenResult + " 开门成功"));//操作日志
//                } else {
//                    return;//重试
//                }
//                OpenRecordEntity openRecord = new OpenRecordEntity();
//                openRecord.setResult(result);
//                openRecord.setTyp(lockOpenResult);
//                openRecord.setMac(bandlock.getMac());
//                openRecordMapper.insertSelective(openRecord);
//
//                //3分钟四次报警
//                if (result == 1) {
//                    Date openTime = new Date();
//                    Date lastTime = DateUtils.subTime(180000L, openTime);
//                    Map<String, Object> map = new LinkedHashMap<>();
//                    map.put("openTime", openTime);//当前失败时间
//                    map.put("lastTime", lastTime); //3分钟之前  上限时间
//                    map.put("mac", bandlock.getMac());
//                    List<OpenRecordEntity> failOpenRecordList = openRecordMapper.queryWarnList(map);
//                    int count = 0;
//                    if (failOpenRecordList.size() >= 4) {
//                        for (OpenRecordEntity failOpenRecord : failOpenRecordList) {
//                            if (failOpenRecord.getResult() == 1) {
//                                count++;
//                                if (count == 4) {
//                                    //推送。。。。。
//                                    JPushUtils.apartmentPush(bandlock.getMobile(), "尊敬的房东您好，" + bandlock.getAlias() + "号房间三分钟内已连续四次开门失败，请及时关注是否为恶意开门！", "安全提醒");
//                                    break;
//                                }
//                            } else {
//                                count = 0;
//                            }
//                        }
//                    }
//                }
//                break;
//
//            default:
//                logger.warn("<<< 硬件端：非法协议？？");
//                return;//重试
//        }
//
//        byte[] successBytes = CustomPackUtils.pack(CustomPackUtils.RESPONSE_SUCCESS_HEX_CMD, CustomPackUtils.SERVER_DEVICE_ID, sourceByte, CustomPackUtils.SERVER_RESPONSE_MSG_ID);
//        ioSession.write(IoBuffer.wrap(successBytes));
//        logger.info(">>> 硬件端：{}({}_{}) 参数：{}", remoteAddressAndSocket, uniqueMac, powerMac, HexUtils.bytesToHexString(successBytes));
//    }
//
//    public static void saveWlt(byte[] picbytes, String idcard) {
//        try {
//            String wltfile = System.getProperty("user.dir") + File.separator + idcard + ".wlt";
//            if (null != picbytes) {
//                DataOutputStream out = new DataOutputStream(
//                        new BufferedOutputStream(
//                                new FileOutputStream(wltfile)));
//                out.write(picbytes);
//                out.close();
//            }
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
//
//    public static void saveBmp(byte[] picbytes) {
//        try {
//            String bmpFile = System.getProperty("user.dir") + File.separator + "hpt.bmp";
//            if (null != picbytes) {
//                DataOutputStream out = new DataOutputStream(
//                        new BufferedOutputStream(
//                                new FileOutputStream(bmpFile)));
//                out.write(picbytes);
//                out.close();
//            }
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
//
//    @Override
//    public void messageSent(IoSession ioSession, Object o) throws Exception {
//    }
//
//    @Override
//    public void inputClosed(IoSession ioSession) throws Exception {
//    }
//
//}